package com.tanhua.server.service;

import com.alibaba.fastjson.JSON;
import com.tanhua.autoconfig.template.HuanXinTemplate;
import com.tanhua.autoconfig.template.TXSMSTemplate;
import com.tanhua.commons.constant.Constants;
import com.tanhua.commons.exception.TanHuaException;
import com.tanhua.commons.utils.JwtUtils;
import com.tanhua.dubbo.api.db.UserApi;
import com.tanhua.model.db.User;
import com.tanhua.model.vo.ErrorResult;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.stereotype.Service;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

// 注册spring容器
@Service
@Slf4j
public class UserService {

    @Autowired
    private TXSMSTemplate txsmsTemplate;

    /**
     *
     * value: 如果想使用java对象，使用redisTemplate<key JDKSerializer, value JDKSerializer>, 在redis客户端中，查看时显示乱码
     *        如果想使用String，使用stringRedisTemplate, 在redis客户端中，查看正常显示
     */
    @Autowired
    private StringRedisTemplate stringRedisTemplate;

    @Autowired
    private HuanXinTemplate huanXinTemplate;

    @DubboReference
    private UserApi userApi;

    /**
     * 注册或登录时，发送验证码
     * @param paramMap
     */
    public void sendValidateCode(Map<String, String> paramMap) {
        // 获取手机号码
        String phone = paramMap.get("phone");
        // 判断是否发送过了, 从redis中读取
        // 拼接key                   2.5亿 key
        String key = "VALIDATE_CODE_" + phone;
        String codeInRedis = stringRedisTemplate.opsForValue().get(key);
        log.info("注册登录redis中的验证：{},{}", phone,codeInRedis);
        // 有值，告诉用户，验证码已经发送过了
        if(StringUtils.isNotEmpty(codeInRedis)){
            throw new TanHuaException(ErrorResult.duplicate());
        }
        // 生成验证码, 随机产生6位随机数字
        String validateCode = "123456";//RandomStringUtils.randomNumeric(6);
        // 发送短信
        //txsmsTemplate.sendValidateCode(phone, validateCode);
        log.info("验证码发送成功!{},{}", phone,validateCode);
        // 存入redis, key, value
        // 设置有效期5分钟
        stringRedisTemplate.opsForValue().set(key, validateCode, 5, TimeUnit.MINUTES);
    }

    /**
     * 注册登录 验证码校验
     * @param paramMap
     * @return
     */
    public Map<String, Object> loginVerification(Map<String, String> paramMap) {
        // 1. 校验验证码  取redis中的验证码与前端传来的验证码比较
        String verificationCode = paramMap.get("verificationCode");
        String phone = paramMap.get("phone");
        // 1.1 拼接key
        String key = "VALIDATE_CODE_" + phone;
        // 1.2 调用redis获取
        String codeInRedis = stringRedisTemplate.opsForValue().get(key);
        log.info("注册登录校验：verificationCode={}, codeInRedis={}", verificationCode, codeInRedis);
        // 1.3 没有值, 过期。 报错，请重新获取验证码
        if(StringUtils.isEmpty(codeInRedis)){
            throw new TanHuaException(ErrorResult.loginError());
        }
        // 1.4 有值，比较redis验证码与前端传来的验证码比较
        if(!StringUtils.equals(codeInRedis, verificationCode)) {
            // 1.5 不同，则报错 验证码错误
            throw new TanHuaException(ErrorResult.validateCodeError());
        }
        // 1.6 相同，删除redis中的key。 防止重复提交
        stringRedisTemplate.delete(key);
        // 2. 如果通过 判断是否已经注册过了, 通过手机号码查询tb_user表select * from tb_user where mobile=手机号码
        User loginUser = userApi.findByMobile(phone);
        boolean isNew = false;
        // 3. 用户不存在 注册为新用户
        if(null == loginUser){
            log.info("用户不存在 {}",phone);
            //注册为新用户
            loginUser = new User();
            loginUser.setMobile(phone);
            String password = phone.substring(5);
            // 加密密码，再设置
            loginUser.setPassword(DigestUtils.md5Hex(password));
            // 添加新用户时返回新注册用户的id
            Long loginUserId = userApi.add(loginUser);
            // 此时的loginUser的id为空值
            loginUser.setId(loginUserId);
            isNew = true;
            // 同步注册环信上的账号
            if (huanXinTemplate.createUser(Constants.HX_USER_PREFIX + loginUserId, Constants.INIT_PASSWORD)) {
                // 注册上了，更新用户表
                User huanXinUser = new User();
                huanXinUser.setId(loginUserId);
                huanXinUser.setHxUser(Constants.HX_USER_PREFIX + loginUserId);
                huanXinUser.setHxPassword(Constants.INIT_PASSWORD);
                userApi.update(huanXinUser);
                // 同步设置用户的环信
                loginUser.setHxUser(Constants.HX_USER_PREFIX + loginUserId);
                loginUser.setHxPassword(Constants.INIT_PASSWORD);
            }
        }
        // 4. 生成token
        String token = JwtUtils.createToken(loginUser.getId(), phone);
        // 4.1 存入redis, key=TOKEN_{token}  value=用户信息
        String tokenKey = "TOKEN_" + token;
        // 4.2 把登录用户信息转成json字符串，存入redis, 且设置3天有效期
        String loginUserJsonString = JSON.toJSONString(loginUser);
        stringRedisTemplate.opsForValue().set(tokenKey, loginUserJsonString, 3, TimeUnit.DAYS);
        // 5. 构建返回值返回
        Map<String,Object> resultMap = new HashMap<>();
        resultMap.put("token", token);
        resultMap.put("isNew", isNew);
        return resultMap;
    }
}
